"""
    2021-08-12  13:52   by  CYL
    历史:
        来自于自己Gitee中帮QQ群友写的xlrd中的newDemo0。
    文件名：
        xlsTools.py
    文件说明：
        整合了.xls中常用的操作函数。
    目前已有功能：
        1)新建一个空白.xls文件。                                     new_xls_File()
        2)将一个.xls文件镜像，保留原文件生成一个新的.xls文件。            mirrow_xls_File()
        3)获取.xls文件的某个Sheet中的行列大小。                        get_xls_line_row_info()
        4)获取.xls中某个Sheet中的单元格数据。                          Catch_xls_cell_value()
        5)生成近乎完整的XFstyle单元格格式。                            Write_xls_cell_XFstyle_chg_ALL()
        6)生成简易版的XFstyle单元格格式。                              Write_xls_cell_XFstyle_Easy()
        7)向某个.xls中的某个Sheet中的单元格里写入内容，也可写入单元格格式。  Write_xls_cell_value()

    后续：
        XFstyle常用的颜色还未归类。
        暂未加入删除单元格。
        暂未加入插入行、删除行。
        暂未加入插入列、删除列。
        暂未加入合并单元格。
        暂未加入拆分单元格。
        暂未加入多行复制和输出至txt或excel或database。
        暂未加入多列复制和输出至txt或excel或database。
        暂未增加数据图像可视化。
"""
import xlrd
import xlutils.copy
#from xlutils.copy import copy #可用于代替上一行的import xlutils.copy
import xlwt
import os

def new_xls_File(xlsStorePath:str="./newXLSfromPy.xls",SheetName:str="Sheet1"):
    """
        2021-08-12  12:57   by  CYL
        函数名：
            new_xls_File()
        函数说明：
            用于新建一个.xls文件。
        关联库：
            os库 xlwt库
    :param xlsStorePath:    想要创建的新.xls文件的路径名。默认为./newXLSfromPy.xls
    :param SheetName:       想要创建的新.xls文件的第一个Sheet名。默认为Sheet1.
    :return:
    """
    if os.path.exists(xlsStorePath):
        #os.remove(xlsStorePath)
        print(f"已存在{xlsStorePath}文件!")
    else:
        the_new_xls = xlwt.Workbook()
        the_new_sheet = the_new_xls.add_sheet(SheetName)
        the_new_xls.save(xlsStorePath)
        print(f"{xlsStorePath}文件创建成功!")

def mirrow_xls_File(GenXls_FilePath:str,MirrorXls_FilePath:str,format_copy:bool=True,encodeType:str="utf-8"):
    """
        2021-08-12  13:21   by  CYL
        函数名：
            mirrow_xls_File()
        函数说明：
            将一个.xls文件的内容复制到一个新的.xls中。
        关联库：
            os库 xlrd库 xlutils库 xlwt库
    :param GenXls_FilePath: 被复制的.xls文件路径。
    :param MirrorXls_FilePath:  新的.xls文件路径。
    :param format_copy: 单元格格式复制，默认复制所有单元格格式。若想消除格式，则传入False即可。
    :param encodeType:  .xls文件字符串编码格式，默认为utf-8.
    :return:
    """
    if os.path.exists(MirrorXls_FilePath):
        #os.remove(xlsStorePath)
        print(f"已存在{MirrorXls_FilePath}文件!")
    else:
        the_book_Gen = xlrd.open_workbook(GenXls_FilePath, encoding_override=encodeType, formatting_info=format_copy)
        book_for_xlwt = xlutils.copy.copy(the_book_Gen)
        book_for_xlwt.save(MirrorXls_FilePath)
        print(f"{GenXls_FilePath}文件已被复制至新的{MirrorXls_FilePath}文件中!")

def get_xls_line_row_info(SheetName:str,xlsFilePath:str,encodeType:str="utf-8")->(int,int):
    """
        2021-08-12  12:39   by  CYL
        函数名：
            get_xls_line_row_info()
        函数用途：
            用于获取当前.xls表格的某个sheet的行列大小。
        注意：
            从1开始计数。
        关联库：
            xlrd库
    :param SheetName:   想要显示行列数的.xls的Sheet名
    :param xlsFilePath: 想要显示行列数的.xls的文件路径名
    :param encodeType:  默认utf-8
    :return:    返回一个元组，即（行数，列数）
    """
    the_book = xlrd.open_workbook(xlsFilePath,encoding_override=encodeType)
    the_sheet = the_book.sheet_by_name(SheetName)
    print(f"{the_sheet.nrows}行，{the_sheet.ncols}列",type(the_sheet.nrows))
    return (the_sheet.nrows,the_sheet.ncols)

def Catch_xls_cell_value(Line:int,Row:int,SheetName:str,xlsFilePath:str,encodeType:str="utf-8") -> str :
    """
    2021-08-12  09:38   by  CYL
    FunctionName:   print_xls_cell_value()
    Explanation:    用于读取某个.xls文件中的某个Sheet中的某一个单元格中的内容。
    关联库：
        xlrd库
    :param Line:    想要读取的单元格所在行。
    :param Row:     想要读取的单元格所在列。
    :param SheetName:   想要读取的单元格所在Sheet名。
    :param xlsFilePath: 想要读取的单元格所在.xls路径名(需包含.xls文件名)。
    :return:    返回读取到的单元格的内容。
    """
    the_book = xlrd.open_workbook(xlsFilePath,encoding_override=encodeType)
    the_sheet = the_book.sheet_by_name(SheetName)
    the_cell_value = str(the_sheet.cell_value(Line, Row))
    print(f"{SheetName}.cell_value({Line},{Row}) = ",the_cell_value,type(the_cell_value),"aim:用于显示print_xls_cell_value()的结果。")
    return the_cell_value

def Write_xls_cell_XFstyle_chg_ALL()->xlwt.Style.XFStyle:
    """
        2021-08-12  11：21   by  CYL & csdn.net
        参考网址：
            1)https://blog.csdn.net/kk123a/article/details/49813559
            2)https://blog.csdn.net/weixin_35757704/article/details/116290252
        函数说明：
            基本上涵盖了所有的XFstyle样式。
            除了Number format和Protection这两个属性没有添加。
            简易版本的可以使用Write_xls_cell_XFstyle_Easy()进行设置。
        关联库：
            xlwt库
    :return:    返回一个XFstyle，可用于Write_xls_cell_value()中的.xls单元格样式设置。
    """
    the_cell_font = xlwt.Font()
    # 字体类型
    the_cell_font.name = "Microsoft YaHei UI"
    # 字体颜色，详见XFstyleColor.png
    the_cell_font.colour_index = 1
    # 字体大小，16为字号，20为衡量单位
    the_cell_font.height = 20 * 16
    # 字体加粗
    the_cell_font.bold = False
    # 下划线
    the_cell_font.underline = True
    # 斜体字
    the_cell_font.italic = True

    # 设置单元格对齐方式
    the_cell_alignment = xlwt.Alignment()
    # 0x01(左端对齐)、0x02(水平方向上居中对齐)、0x03(右端对齐)
    the_cell_alignment.horz = 0x02
    # 0x00(上端对齐)、 0x01(垂直方向上居中对齐)、0x02(底端对齐)
    the_cell_alignment.vert = 0x01
    # 设置自动换行
    the_cell_alignment.wrap = 1

    # 设置边框
    the_cell_borders = xlwt.Borders()
    # 细实线:1，小粗实线:2，细虚线:3，中细虚线:4，大粗实线:5，双线:6，细点虚线:7
    # 大粗虚线:8，细点划线:9，粗点划线:10，细双点划线:11，粗双点划线:12，斜点划线:13
    the_cell_borders.left = 1
    the_cell_borders.right = 2
    the_cell_borders.top = 3
    the_cell_borders.bottom = 4
    the_cell_borders.left_colour = 1
    the_cell_borders.right_colour = 2
    the_cell_borders.top_colour = 3
    the_cell_borders.bottom_colour = 4

    # 设置背景颜色
    the_cell_pattern = xlwt.Pattern()
    # 设置背景颜色的模式
    the_cell_pattern.pattern = xlwt.Pattern.SOLID_PATTERN
    # 背景颜色
    the_cell_pattern.pattern_fore_colour = 3

    # 初始化样式
    the_cell_XFstyle_ALL = xlwt.XFStyle()
    the_cell_XFstyle_ALL.font = the_cell_font  # 设置字体
    the_cell_XFstyle_ALL.alignment = the_cell_alignment  # 设置对齐方式
    the_cell_XFstyle_ALL.borders = the_cell_borders  # 设置边框
    the_cell_XFstyle_ALL.pattern = the_cell_pattern  # 设置背景颜色
    return the_cell_XFstyle_ALL

def Write_xls_cell_XFstyle_Easy(XFstyleName:str="myStyle_WR")->xlwt.Style.XFStyle:
    """
        2021-08-12  11:25   by  CYL
        历史：
            是Write_xls_cell_XFstyle_chg_ALL()的简化版。
        函数名：
            Write_xls_cell_XFstyle_Easy()
        函数用途：
            常用的样式集合。
        参数值：
            1)XFstyleName：用于常用的样式选择。默认红底白字居中显示。
        返回值：
             返回一个XFstyle，可用于Write_xls_cell_value()中的.xls单元格样式设置。
        关联库：
            xlwt库
    :param XFstyleName:
    :return:
    """
    the_cell_font = xlwt.Font()
    the_cell_pattern = xlwt.Pattern()
    the_cell_alignment = xlwt.Alignment()
    if XFstyleName == "myStyle_WR":  #    myStyle_WR:  白字红底居中。
        the_cell_font.colour_index = 1
        the_cell_pattern.pattern = xlwt.Pattern.SOLID_PATTERN
        the_cell_pattern.pattern_fore_colour = 2
        the_cell_alignment.horz = 0x02
        the_cell_alignment.vert = 0x01
    elif XFstyleName == "myStyle_RW":#    myStyle_RW:  红字白底居中。
        the_cell_font.colour_index = 2
        the_cell_pattern.pattern = xlwt.Pattern.SOLID_PATTERN
        the_cell_pattern.pattern_fore_colour = 1
        the_cell_alignment.horz = 0x02
        the_cell_alignment.vert = 0x01
    elif XFstyleName == "myStyle_WB":#   myStyle_WB:  白字蓝底居中。
        the_cell_font.colour_index = 1
        the_cell_pattern.pattern = xlwt.Pattern.SOLID_PATTERN
        the_cell_pattern.pattern_fore_colour = 4
        the_cell_alignment.horz = 0x02
        the_cell_alignment.vert = 0x01
    elif XFstyleName == "myStyle_BW":#   myStyle_BW:  蓝字白底居中。
        the_cell_font.colour_index = 4
        the_cell_pattern.pattern = xlwt.Pattern.SOLID_PATTERN
        the_cell_pattern.pattern_fore_colour = 1
        the_cell_alignment.horz = 0x02
        the_cell_alignment.vert = 0x01
    elif XFstyleName == "myStyle_WG":#   myStyle_WG:  白字绿底居中。
        the_cell_font.colour_index = 1
        the_cell_pattern.pattern = xlwt.Pattern.SOLID_PATTERN
        the_cell_pattern.pattern_fore_colour = 17
        the_cell_alignment.horz = 0x02
        the_cell_alignment.vert = 0x01
    elif XFstyleName == "myStyle_GW":#   myStyle_GW:  绿字白底居中。
        the_cell_font.colour_index = 17
        the_cell_pattern.pattern = xlwt.Pattern.SOLID_PATTERN
        the_cell_pattern.pattern_fore_colour = 1
        the_cell_alignment.horz = 0x02
        the_cell_alignment.vert = 0x01
    elif XFstyleName == "myStyle_CYAN":#   myStyle_cyan:  黑字粗体cyan底居中。
        the_cell_font.colour_index = 0
        the_cell_font.bold = True
        the_cell_pattern.pattern = xlwt.Pattern.SOLID_PATTERN
        the_cell_pattern.pattern_fore_colour = 7
        the_cell_alignment.horz = 0x02
        the_cell_alignment.vert = 0x01
    else:
        pass
    the_cell_XFstyle_Easy = xlwt.XFStyle()
    the_cell_XFstyle_Easy.font = the_cell_font  # 设置字体
    the_cell_XFstyle_Easy.alignment = the_cell_alignment  # 设置对齐方式
    the_cell_XFstyle_Easy.pattern = the_cell_pattern  # 设置背景颜色
    return the_cell_XFstyle_Easy

def Write_xls_cell_value(Line:int,Row:int,cellContent:str,SheetName:str,xlsFilePath:str,XFstyle:xlwt.Style.XFStyle=None,encodeType:str="utf-8"):
    """
        2021-08-12  13:07   by  CYL
        函数说明：   用于向.xls文件中的某个sheet中的某个单元格写入内容 或 内容和样式。
        关联库：
            xlrd库 xlutils库 xlwt库
    :param Line:    想要写入的单元格的行。
    :param Row:     想要写入的单元格的列。
    :param cellContent: 想要写入单元格中的内容。
    :param SheetName:   想要写入单元格所在的Sheet名。
    :param xlsFilePath: 想要写入单元格所在的.xls文件路径。
    :param XFstyle: 想要写入的单元格的格式，默认为无。可由Write_xls_cell_XFstyle_Easy()或Write_xls_cell_XFstyle_chg_ALL()生成。
    :param encodeType:  .xls的字符编码格式，默认为utf-8。
    :return:    返回xlwt的book句柄。
    """
    if XFstyle == None:
        the_book_Gen = xlrd.open_workbook(xlsFilePath,encoding_override=encodeType,formatting_info = True)
        book_for_xlwt = xlutils.copy.copy(the_book_Gen)
        sheet_for_xlwt = book_for_xlwt.get_sheet(SheetName)
        sheet_for_xlwt.write(Line,Row,cellContent)
        book_for_xlwt.save(xlsFilePath)
    else:
        the_book_Gen = xlrd.open_workbook(xlsFilePath,encoding_override=encodeType,formatting_info = True)
        book_for_xlwt = xlutils.copy.copy(the_book_Gen)
        sheet_for_xlwt = book_for_xlwt.get_sheet(SheetName)
        sheet_for_xlwt.write(Line,Row,cellContent,XFstyle)
        book_for_xlwt.save(xlsFilePath)
    return book_for_xlwt

def xls_demo():
    """
        2021-08-12  13:48   by  CYL
        函数名：
            xls_demo()
        函数说明：
            用于展示本.py文件中的函数的使用方法。
            可直接在main()中使用。
    :return:
    """
    xlsFile_Path = r"./EXCEL_FILE/demo0.xls"
    #   获取Sheet1的第0行第2列的内容，即实际excel中的第1行第3列的内容。
    Catch_xls_cell_value(0,2,"Sheet1",xlsFile_Path)
    #   将原.xls文件直接复制到新的.xls文件中(复制的过程中会直接新建.xls文件)。
    new_xlsFile_Path = r"./123.xls"
    mirrow_xls_File(xlsFile_Path,new_xlsFile_Path)
    #   在.xls文件中的第0行第0列写入内容。
    cell_content = "你好，世界！"
    Write_xls_cell_value(0,0,cell_content,"Sheet1",xlsFile_Path)
    #   在.xls文件中的第1行第1列及第2行第2列写入内容和修改单元格样式。
    cell_style = Write_xls_cell_XFstyle_Easy()
    Write_xls_cell_value(1,1,"啦啦啦！","Sheet1",xlsFile_Path,XFstyle=cell_style)
    Write_xls_cell_value(2,2, "乌拉！", "Sheet1",xlsFile_Path,XFstyle=cell_style)
    #   获取.xls的行列数
    get_xls_line_row_info("Sheet1",xlsFile_Path)
    #   新建一个空白的.xls文件
    new_xls_File()